home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 1.toast / pc / sample code / graphics 2d / calccmask & calcmask / calcmask.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  7.0 KB  |  260 lines

  1. /*
  2.     File:        CalcCMask & CalcMask.c
  3.  
  4.     Contains:    This snippet shows how to use both CalcCMask or                
  5.                 CalcMask to create a mask given a source bitmap                
  6.                 image.  As decribed on pages IV-24 and V-72 of                
  7.                 Inside Mac, the two routines compute a destination                
  8.                 bitmap image with 1's only in the pixels where                
  9.                 paint can not leak from any of the outer edges.            
  10.                 This is similar to the lasso tool found in many                
  11.                 drawing apps.                    
  12.  
  13.     Written by: Edgar Lee    
  14.  
  15.     Copyright:    Copyright © 1992-1999 by Apple Computer, Inc., All Rights Reserved.
  16.  
  17.                 You may incorporate this Apple sample source code into your program(s) without
  18.                 restriction. This Apple sample source code has been provided "AS IS" and the
  19.                 responsibility for its operation is yours. You are not permitted to redistribute
  20.                 this Apple sample source code as "Apple sample source code" after having made
  21.                 changes. If you're going to re-distribute the source, we require that you make
  22.                 it clear in the source that the code was descended from Apple sample source
  23.                 code, but that you've made changes.
  24.  
  25.     Change History (most recent first):
  26.                 7/8/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  27.                 
  28.  
  29. */
  30.  
  31. #include <Dialogs.h>
  32. #include <Fonts.h>
  33. #include <QDOffscreen.h>
  34. #include <Resources.h>
  35. /* Constant Declarations */
  36.  
  37. #define    WWIDTH        176
  38. #define    WHEIGHT        106
  39.  
  40. #define WLEFT        (((qd.screenBits.bounds.right - qd.screenBits.bounds.left) - WWIDTH) / 2)
  41. #define WTOP        (((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - WHEIGHT) / 2)
  42.  
  43. /* Global Variable Definitions */
  44.  
  45. WindowPtr    gWindow;
  46.  
  47. void initMac();
  48. void createWindow();
  49. void doCalcCMaskExample();
  50.  
  51. void DisposeGrafPort();
  52. GrafPtr CreateGrafPort();
  53.  
  54. void doEventLoop();
  55.  
  56. void main(void)
  57. {
  58.     initMac();
  59.     
  60.     createWindow();
  61.     
  62.     doEventLoop();
  63. }
  64.  
  65. void initMac()
  66. {
  67.     MaxApplZone();
  68.     
  69.     InitGraf( &qd.thePort );
  70.     InitFonts();
  71.     InitWindows();
  72.     InitMenus();
  73.     TEInit();
  74.     InitDialogs( nil );
  75.     InitCursor();
  76.     FlushEvents( 0, everyEvent );
  77. }
  78.  
  79. void createWindow()
  80. {
  81.     Rect rect;
  82.     
  83.     SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  84.     
  85.     gWindow = NewCWindow( 0L, &rect, "\pCalc-C-Mask", true, documentProc,
  86.                             (WindowPtr)-1L, true, 0L );
  87.                             
  88.     SetPort( gWindow );
  89. }
  90.  
  91. #define    COLOR_VERSION
  92.  
  93. void doCalcCMaskExample()
  94. {
  95.     PicHandle    pict;                /* B/W Pict used to create mask. */
  96.     GWorldPtr    gworld;                /* Gworld used for CopyMask source. */
  97.     GrafPtr     mask;                /* Mask created by CalcCMask. */
  98.     GrafPtr        sourceForMask;        /* Bitmap of pict image used for creating mask. */
  99.     RGBColor    seedColor;            /* Color used to determine the mask. */
  100.     Rect        rect;                /* Bounding rect of mask and source. */
  101.     CGrafPtr    currentPort;        /* Saved CGrafPtr for later restore. */
  102.     GDHandle    currentDevice;        /* Saved device for later restore. */
  103.     
  104.     /* Load the pict resource to be used for the mask. */
  105.     pict = (PicHandle)GetResource( 'PICT', 128 );
  106.     
  107.     /* Define the bounding rect for the source and mask bitmap. */
  108.     rect = (**pict).picFrame;
  109.     OffsetRect( &rect, -rect.left, -rect.top );
  110.     
  111.     /* Allocate the source bitmap for which the mask will be created from. */
  112.     sourceForMask = CreateGrafPort( &rect );
  113.     
  114.     /* Create the source bitmap's image by using the pict. */
  115.     SetPort( sourceForMask );
  116.     DrawPicture( pict, &rect );
  117.     SetPort( gWindow );
  118.     
  119.     /* Release the memory used by the pict. */
  120.     ReleaseResource( (Handle)pict );
  121.  
  122.     /* Create a gworld of a blue rectangle for the CopyMask source. */
  123.     GetGWorld( ¤tPort, ¤tDevice );
  124.     NewGWorld( &gworld, 8, &rect, nil, nil, 0 );
  125.     SetPort( (GrafPtr)gworld );
  126.     ForeColor( blueColor );
  127.     PaintRect( &rect );
  128.     SetGWorld( currentPort, currentDevice );
  129.     
  130.     /* Copy the source image to the window to see what the mask was created from. */
  131.     CopyBits( &sourceForMask->portBits, &gWindow->portBits,
  132.                 &sourceForMask->portRect, &rect, srcCopy, nil );
  133.     
  134.     /* Allocate the bitmap for the mask. */
  135.     mask = CreateGrafPort( &sourceForMask->portRect );
  136.  
  137. #ifdef COLOR_VERSION
  138.  
  139.     /* Create a mask from the source bitmap of all colors that match the seedColor. */
  140.     seedColor.red = seedColor.green = seedColor.blue = 0;
  141.     
  142.     CalcCMask( &sourceForMask->portBits, &mask->portBits, &sourceForMask->portRect,
  143.                 &mask->portRect, &seedColor, nil, 0 );
  144.  
  145. #else
  146.  
  147.     CalcMask( &sourceForMask->portBits.baseAddr, &mask->portBits.baseAddr,
  148.                 sourceForMask->portBits.rowBytes, mask->portBits.rowBytes,
  149.                 sourceForMask->portRect.bottom - sourceForMask->portRect.top,
  150.                 sourceForMask->portBits.rowBytes >> 1 );
  151.  
  152. #endif
  153.  
  154.     /* Now draw the blue rectangle with its mask. */
  155.     OffsetRect( &rect, sourceForMask->portRect.right, 0 );
  156.     CopyMask( (BitMap*)&(*gworld).portPixMap, &mask->portBits, &gWindow->portBits,
  157.                 &sourceForMask->portRect, &mask->portRect, &rect );
  158.  
  159.     /* Release the used memory. */
  160.     DisposeGrafPort( sourceForMask );
  161.     DisposeGrafPort( mask );
  162.     DisposeGWorld( gworld );
  163. }
  164.  
  165. GrafPtr CreateGrafPort( bounds )    /* Originally written by Forrest Tanaka. */
  166. Rect *bounds;
  167. {
  168.     GrafPtr    savedPort;        /* Saved GrafPtr for later restore. */
  169.     GrafPtr    newPort;        /* New GrafPort. */
  170.     Rect    localBounds;    /* Local copy of bounds. */
  171.  
  172.     GetPort( &savedPort );
  173.  
  174.     /* Set the top-left corner of bounds to (0,0). */
  175.     localBounds = *bounds;
  176.     OffsetRect( &localBounds, -bounds->left, -bounds->top );
  177.  
  178.     /* Allocate a new GrafPort. */
  179.     newPort = (GrafPtr)NewPtrClear( sizeof( GrafPort ) );
  180.     
  181.     if (newPort != nil)
  182.     {
  183.         /* Initialize the new port and make the current port. */
  184.         OpenPort( newPort );
  185.  
  186.         /* Initialize and allocate the bitmap. */
  187.         newPort->portBits.bounds = localBounds;
  188.           newPort->portBits.rowBytes = ((localBounds.right + 15) >> 4) << 1;
  189.         newPort->portBits.baseAddr =  NewPtrClear( newPort->portBits.rowBytes *
  190.                                                     (long)localBounds.bottom );
  191.         if (newPort->portBits.baseAddr != nil)
  192.         {
  193.             /* Clean up the new port. */
  194.             newPort->portRect = localBounds;
  195.             ClipRect( &localBounds );
  196.             RectRgn( newPort->visRgn, &localBounds );
  197.             EraseRect( &localBounds );
  198.         }
  199.         else
  200.         {
  201.             /* Allocation failed; deallocate the port. */
  202.             ClosePort( newPort );
  203.             DisposePtr( (Ptr)newPort );
  204.             newPort = nil;
  205.         }
  206.     }
  207.     
  208.     SetPort( savedPort );
  209.     return newPort;
  210. }
  211.  
  212. void DisposeGrafPort( doomedPort )        /* Originally written by Forrest Tanaka. */
  213. GrafPtr doomedPort;
  214. {
  215.     ClosePort( doomedPort );
  216.     DisposePtr( doomedPort->portBits.baseAddr );
  217.     DisposePtr( (Ptr)doomedPort );
  218. }
  219.  
  220. void doEventLoop()
  221. {
  222.     EventRecord event;
  223.     WindowPtr   window;
  224.     short       clickArea;
  225.     Rect        screenRect;
  226.  
  227.     for (;;)
  228.     {
  229.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  230.         {
  231.             if (event.what == mouseDown)
  232.             {
  233.                 clickArea = FindWindow( event.where, &window );
  234.                 
  235.                 if (clickArea == inDrag)
  236.                 {
  237.                     screenRect = (**GetGrayRgn()).rgnBBox;
  238.                     DragWindow( window, event.where, &screenRect );
  239.                 }
  240.                 else if (clickArea == inContent)
  241.                 {
  242.                     if (window != FrontWindow())
  243.                         SelectWindow( window );
  244.                 }
  245.                 else if (clickArea == inGoAway)
  246.                     if (TrackGoAway( window, event.where ))
  247.                         return;
  248.             }
  249.             else if (event.what == updateEvt)
  250.             {
  251.                 window = (WindowPtr)event.message;    
  252.                 SetPort( window );
  253.                 
  254.                 BeginUpdate( window );
  255.                 doCalcCMaskExample();
  256.                 EndUpdate( window );
  257.             }
  258.         }
  259.     }
  260. }